package com.meida.module.admin.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.meida.common.exception.OpenAlertException;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.entity.EntityMap;
import com.meida.common.mybatis.model.PageParams;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.http.OpenRestTemplate;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.FlymeUtils;
import com.meida.module.admin.client.constants.BaseConstants;
import com.meida.module.admin.client.constants.ResourceType;
import com.meida.module.admin.client.entity.BaseMenu;
import com.meida.module.admin.provider.mapper.BaseMenuMapper;
import com.meida.module.admin.provider.service.BaseActionService;
import com.meida.module.admin.provider.service.BaseAuthorityService;
import com.meida.module.admin.provider.service.BaseMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author zyf
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class BaseMenuServiceImpl extends BaseServiceImpl<BaseMenuMapper, BaseMenu> implements BaseMenuService {
    @Autowired
    private BaseMenuMapper baseMenuMapper;
    @Autowired
    private BaseActionService baseActionService;
    @Autowired
    private BaseAuthorityService baseAuthorityService;

    @Autowired
    private OpenRestTemplate openRestTemplate;

    @Value("${spring.application.name}")
    private String DEFAULT_SERVICE_ID;

    /**
     * 分页查询
     *
     * @param pageParams
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public IPage<BaseMenu> findListPage(PageParams pageParams) {
        BaseMenu query = pageParams.mapToObject(BaseMenu.class);
        QueryWrapper<BaseMenu> queryWrapper = new QueryWrapper();
        queryWrapper.lambda()
                .likeRight(FlymeUtils.isNotEmpty(query.getMenuCode()), BaseMenu::getMenuCode, query.getMenuCode())
                .likeRight(FlymeUtils.isNotEmpty(query.getMenuName()), BaseMenu::getMenuName, query.getMenuName());
        return baseMenuMapper.selectPage(new Page(pageParams.getPage(), pageParams.getLimit()), queryWrapper);
    }

    /**
     * 查询列表
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<BaseMenu> findAllList() {
        List<BaseMenu> list = baseMenuMapper.selectList(new QueryWrapper<>());
        //根据优先级从小到大排序
        list.sort((BaseMenu h1, BaseMenu h2) -> h1.getPriority().compareTo(h2.getPriority()));
        return list;
    }

    /**
     * 根据主键获取菜单
     *
     * @param menuId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public BaseMenu getMenu(Long menuId) {
        return baseMenuMapper.selectById(menuId);
    }

    /**
     * 检查菜单编码是否存在
     *
     * @param menuCode
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Boolean isExist(String menuCode) {
        QueryWrapper<BaseMenu> queryWrapper = new QueryWrapper();
        queryWrapper.lambda()
                .eq(BaseMenu::getMenuCode, menuCode);
        int count = baseMenuMapper.selectCount(queryWrapper);
        return count > 0 ? true : false;
    }

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BaseMenu menu, EntityMap extra) {
        String menuCode = cs.getParams("menuCode");
        Long parentId = cs.getLong("parentId");
        Integer priority = cs.getInt("priority",0);
        if (isExist(menuCode)) {
            throw new OpenAlertException(String.format("%s编码已存在!", menuCode));
        }
        if (parentId == null) {
            menu.setParentId(0L);
        }
        if (priority == null) {
            menu.setPriority(0);
        }

        menu.setIsPersist(0);
        menu.setServiceId(DEFAULT_SERVICE_ID);
        return ResultBody.ok();
    }

    @Override
    public ResultBody afterAdd(CriteriaSave cs, BaseMenu baseMenu,EntityMap extra) {
        // 同步权限表里的信息
        baseAuthorityService.saveOrUpdateAuthority(baseMenu.getMenuId(), ResourceType.menu);
        return ResultBody.ok("保存成功");
    }


    @Override
    public ResultBody beforeEdit(CriteriaUpdate<BaseMenu> cu,BaseMenu menu) {
        Long menuId = cu.getParams("menuId");
        Long parentId = cu.getLong("parentId");
        Integer priority = cu.getInt("priority",0);
        String menuCode = cu.getParams("menuCode");
        BaseMenu check = getMenu(menuId);
        ApiAssert.isNotEmpty("菜单不存在", check);
        if (!check.getMenuCode().equals(menuCode)) {
            // 和原来不一致重新检查唯一性
            if (isExist(menuCode)) {
                ApiAssert.failure("编码已存在");
            }
        }
        if (parentId == null) {
            menu.setParentId(0L);
        }
        if (priority == null) {
            menu.setPriority(0);
        }
        return ResultBody.ok();
    }

    @Override
    public ResultBody afterEdit(CriteriaUpdate cu, BaseMenu baseMenu) {
        openRestTemplate.refreshGateway();
        // 同步权限表里的信息
        baseAuthorityService.saveOrUpdateAuthority(baseMenu.getMenuId(), ResourceType.menu);
        return ResultBody.msg("更新成功");
    }

    @Override
    public ResultBody beforeDelete(CriteriaDelete<BaseMenu> cd) {
        Long menuId = cd.getIdValue();
        BaseMenu menu = getMenu(menuId);
        if (menu != null && menu.getIsPersist().equals(BaseConstants.ENABLED)) {
            throw new OpenAlertException(String.format("基础数据,不允许删除!"));
        }
        return ResultBody.ok();
    }

    /**
     * 查询接口
     *
     * @param apiCode
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public BaseMenu getMenu(String menuName) {
        QueryWrapper<BaseMenu> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseMenu::getMenuName, menuName);
        return getOne(queryWrapper);
    }

    @Override
    public ResultBody afterDelete(CriteriaDelete cd, Long[] ids) {
        // 移除菜单权限
        baseAuthorityService.removeAuthority(ids[0], ResourceType.menu);
        // 移除功能按钮和相关权限
        baseActionService.removeByMenuId(ids[0]);
        //刷新网关
        openRestTemplate.refreshGateway();
        return ResultBody.msg("删除成功");
    }
}
